#ifndef FLASH_H
#define FLASH_H

#include "sysTick.h"
#include <stm32f4xx.h>

// Flash地址
#define FLASH_END_ADDR 0x1FFFFF   // Flash结束地址
#define FLASH_START_ADDR 0x000000 // Flash起始地址

// Flash参数
#define FLASH_BLOCK_NUM 32                              // Flash块区数量
#define FLASH_PAGE_SIZE 256                             // Flash页区大小
#define FLASH_SECTOR_SIZE (16 * FLASH_PAGE_SIZE)        // Flash扇区大小
#define FLASH_BLOCK_SIZE (16 * FLASH_SECTOR_SIZE)       // Flash块区大小
#define FLASH_SIZE (FLASH_BLOCK_NUM * FLASH_BLOCK_SIZE) // Flash总共容量

// Flash引脚
#define FLASH_CS GPIO_Pin_0   // CS
#define FLASH_SCK GPIO_Pin_3  // SCK
#define FLASH_MISO GPIO_Pin_4 // MISO
#define FLASH_MOSI GPIO_Pin_5 // MOSI

// SPI引脚
#define FLASH_SPI_SCK GPIO_PinSource3  // SCK
#define FLASH_SPI_MISO GPIO_PinSource4 // MISO
#define FLASH_SPI_MOSI GPIO_PinSource5 // MOSI

// GPIO
#define FLASH_GPIO GPIOB                                                                 // GPIOB组
#define FLASH_GPIO_Pin (FLASH_SCK | FLASH_MISO | FLASH_MOSI)                             // FLASH脚
#define FLASH_RCC_APBPeriphClockCmd RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE)  // APB时钟
#define FLASH_RCC_AHBPeriphClockCmd RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE) // AHB时钟

// SPI
#define FLASH_SPI SPI1                 // SPI1组
#define FLASH_GPIO_AF_SPI GPIO_AF_SPI1 // 复用SPI

// CS
#define FLASH_CS_Clr() GPIO_ResetBits(FLASH_GPIO, FLASH_CS) // 拉低
#define FLASH_CS_Set() GPIO_SetBits(FLASH_GPIO, FLASH_CS)   // 拉高

/**
 * @name FLASH初始化
 * @description
 * @function
 * @returns {void}
 * @requires []
 */
void flash_init(void);

/**
 * @name 获取Id
 * @description
 * @function
 * @returns {uint16_t} Id
 * @requires []
 */
uint16_t flash_getId(void);

/**
 * @name 清空整片
 * @description
 * @function
 * @returns {void}
 * @requires []
 */
void flash_erase(void);

/**
 * @name 读取数据
 * @description
 * @function
 * @param {uint8_t} *buffer 数据
 * @param {uint32_t} address 地址
 * @param {uint32_t} size 大小
 * @returns {void}
 * @requires [buffer,address,size]
 */
void flash_read(uint8_t *buffer, const uint32_t address, const uint32_t size);

/**
 * @name 写入数据
 * @description
 * @function
 * @param {uint8_t} *buffer 数据
 * @param {uint32_t} address 地址
 * @param {uint32_t} size 大小
 * @returns {void}
 * @requires [buffer,address,size]
 */
void flash_write(const uint8_t *buffer, const uint32_t address, const uint32_t size);
#endif
